#pragma once


namespace Melting
{
namespace Parallel
{
	//--------------------------------------------------------------------------------------------------------------------	
#ifdef WIN32
	typedef SRWLOCK				RWLockHandle;

#else // pthread
	typedef pthread_rwlock_t 	RWLockHandle;

#endif

	//--------------------------------------------------------------------------------------------------------------------
	// NB : on Windows, RWLock is available only from Windows Vista, and TryLockXXX() only from Windows Seven
	class RWLock
	{
	public:

		inline RWLock	( void );
		inline ~RWLock	( void );

		/// Try to lock for read access (only 1 try) - returns true if successful
		inline bool		TryLockRead	( void );
		/// Lock for read access 
		inline void		LockRead	( void );
		/// Unlock from read access
		inline void		UnlockRead	( void );

		/// Try to lock for read-write access (only 1 try) - returns true if successful
		inline bool		TryLockWrite( void );
		/// Lock for read-write access 
		inline void		LockWrite	( void );
		/// Unlock from read-write access
		inline void		UnlockWrite	( void );

	private:

		RWLockHandle	mHandle;
	};


#ifdef WIN32

	//----------------------------------------------------------------
	//----------------------------------------------------------------
	RWLock::RWLock( void )
	{
		InitializeSRWLock( & mHandle );
	}
	//----------------------------------------------------------------
	//----------------------------------------------------------------
	RWLock::~RWLock( void )
	{
		// NOTHING
	}

	//----------------------------------------------------------------
	//----------------------------------------------------------------
	bool RWLock::TryLockRead( void )
	{
		return 0 != TryAcquireSRWLockShared( & mHandle );
	}
	//----------------------------------------------------------------
	//----------------------------------------------------------------
	void RWLock::LockRead( void )
	{
		AcquireSRWLockShared( & mHandle );
	}
	//----------------------------------------------------------------
	//----------------------------------------------------------------
	void RWLock::UnlockRead( void )
	{
		ReleaseSRWLockShared( & mHandle );
	}

	//----------------------------------------------------------------
	//----------------------------------------------------------------
	bool RWLock::TryLockWrite( void )
	{
		return 0 != TryAcquireSRWLockExclusive( & mHandle );
	}
	//----------------------------------------------------------------
	//----------------------------------------------------------------
	void RWLock::LockWrite( void )
	{
		AcquireSRWLockExclusive( & mHandle );
	}
	//----------------------------------------------------------------
	//----------------------------------------------------------------
	void RWLock::UnlockWrite( void )
	{
		ReleaseSRWLockExclusive( & mHandle );
	}


#else// PTHREAD

	//----------------------------------------------------------------
	//----------------------------------------------------------------
	RWLock::RWLock( void )
	{
		pthread_rwlock_init( & mHandle );
	}
	//----------------------------------------------------------------
	//----------------------------------------------------------------
	RWLock::~RWLock( void )
	{
		pthread_rwlock_destroy( & mHandle );
	}
	//----------------------------------------------------------------
	//----------------------------------------------------------------
	bool RWLock::TryLockRead( void )
	{
		return 0 == pthread_rwlock_tryrdlock( & mHandle );
	}
	//----------------------------------------------------------------
	//----------------------------------------------------------------
	bool RWLock::LockRead( void )
	{
		INT32 iResult = pthread_rwlock_rdlock( & mHandle );
		MB_ASSERT( 0 == iResult );
	}
	//----------------------------------------------------------------
	//----------------------------------------------------------------
	bool RWLock::UnlockRead( void )
	{
		INT32 iResult =  pthread_rwlock_unlock( & mHandle );
		MB_ASSERT( 0 == iResult );
	}
	//----------------------------------------------------------------
	//----------------------------------------------------------------
	bool RWLock::TryLockWrite( void )
	{
		return 0 == pthread_rwlock_trywrlock( & mHandle );
	}
	//----------------------------------------------------------------
	//----------------------------------------------------------------
	bool RWLock::LockWrite( void )
	{
		INT32 iResult = pthread_rwlock_wrlock( & mHandle );
		MB_ASSERT( 0 == iResult );
	}
	//----------------------------------------------------------------
	//----------------------------------------------------------------
	bool RWLock::UnlockWrite( void )
	{
		INT32 iResult = pthread_rwlock_unlock( & mHandle );
		MB_ASSERT( 0 == iResult );
	}

#endif 
}
}// namespace Melting